fn main() {
    // test_if
    // test_if();

    // while 循环
    // test_while();

    //  loop 循环
    // test_loop();

    // for 循环
    // test_for();
    // test_for2();

    // match 表达式
    // match_test();

    // if_let(); 匹配 some(T)
    // if_let_else();

    // 匹配 Option
    // match_option();

    // 匹配 运算 - 卫语句
    // match_guard();

    // match 提供了 @ 符号来绑定变量到名称：
    // math_binding();

    // match_if_let
    match_if_let();

    // 和 if let 类似，while let 也可以把别扭的 match 改写得好看一些
    match_while_let();
}

fn match_while_let() {
    // 将 `optional` 设为 `Option<i32>` 类型
    let mut optional = Some(0);

    // 这读作：当 `let` 将 `optional` 解构成 `Some(i)` 时，就
    // 执行语句块（`{}`）。否则就 `break`。
    while let Some(i) = optional {
        if i > 9 {
            println!("Greater than 9, quit!");
            optional = None;
        } else {
            println!("`i` is `{:?}`. Try again.", i);
            optional = Some(i + 1);
        }
        // ^ 使用的缩进更少，并且不用显式地处理失败情况。
    }
    // ^ `if let` 有可选的 `else`/`else if` 分句，
    // 而 `while let` 没有。
}

#[allow(dead_code)]
fn match_if_let() {
    // 将 `optional` 定为 `Option<i32>` 类型
    let optional = Some(7);

    match optional {
        Some(i) => {
            println!("This is a really long string and `{:?}`", i);
            // ^ 行首需要 2 层缩进。这里从 optional 中解构出 `i`。
            // 译注：正确的缩进是好的，但并不是 “不缩进就不能运行” 这个意思。
        }
        _ => {} // ^ 必须有，因为 `match` 需要覆盖全部情况。不觉得这行很多余吗？
    };
}

#[allow(dead_code)]
fn math_binding() {
    fn age() -> u32 {
        15
    }

    println!("Tell me what type of person you are, ");

    match age() {
        0 => println!("I haven't celebrated my first birthday yet"),
        // 可以直接匹配（`match`） 1 ..= 12，但那样的话孩子会是几岁？
        // 相反，在 1 ..= 12 分支中绑定匹配值到 `n` 。现在年龄就可以读取了。
        n @ 1..=12 => println!("I'm a child of age {:?}", n),
        n @ 13..=19 => println!("I'm a teen of age {:?}", n),
        // 不符合上面的范围。返回结果。
        n => println!("I'm an old person of age {:?}", n),
    }

    //  绑定来结构枚举
    fn some_number() -> Option<u32> {
        Some(42)
    }

    match some_number() {
        // 得到 `Some` 可变类型，如果它的值（绑定到 `n` 上）等于 42，则匹配。
        Some(n @ 42) => println!("The Answer: {}!", n),
        // 匹配任意其他数字。
        Some(n) => println!("Not interesting... {}", n),
        // 匹配任意其他值（`None` 可变类型）。
        _ => (),
    }
}

#[allow(dead_code)]
fn match_guard() {
    let pair = (2, -2);
    // 试一试 ^ 将不同的值赋给 `pair`

    println!("Tell me about {:?}", pair);
    match pair {
        (x, y) if x == y => println!("These are twins"),
        // ^ `if` 条件部分是一个卫语句
        (x, y) if x + y == 0 => println!("Antimatter, kaboom!"),
        (x, _) if x % 2 == 1 => println!("The first one is odd"),
        _ => println!("No correlation..."),
    }
}

// 匹配 Option<T>
// 使用 Option<T> 时，是为了从 Some 中取出其内部的 T 值；
fn plus_one(x: Option<i32>) -> Option<i32> {
    match x {
        None => None,
        Some(i) => Some(i + 1),
    }
}

#[allow(dead_code)]
fn match_option() {
    let five = Some(5);
    let six = plus_one(five);
    let none = plus_one(None);
    println!("six: {:?}, none: {:?}", six, none);
}

#[allow(dead_code)]
fn match_test() {
    match 1 {
        1 => println!("one"),
        2 => println!("two"),
        _ => println!("other"),
    }
}

#[allow(dead_code)]
fn test_for2() {
    let a = [10, 20, 30, 40, 50];

    for element in a {
        println!("the value is: {}", element);
    }

    // for number in (1..4).rev() {
    for number in (1..4).rev() {
        println!("{}!", number);
    }
    println!("LIFTOFF!!!");
}

#[allow(dead_code)]
fn test_for() {
    let a = [10, 20, 30, 40, 50];
    let mut sum = 0;

    for element in a.iter() {
        println!("the value is: {}", element);
        sum += 1;
    }

    println!("sum total :{}", sum)
}

#[allow(dead_code)]
fn test_loop() {
    let mut counter = 0;

    loop {
        counter += 1;

        if counter == 10 {
            break;
        }
    }

    println!("Loop count: {}", counter);
}

#[allow(dead_code)]
fn test_while() {
    let mut number = 3;

    while number != 0 {
        println!("{}!", number);
        number -= 1;
    }

    println!("LIFTOFF!!!");
}

#[allow(dead_code)]
fn test_if() {
    let number = 6;

    if number % 4 == 0 {
        println!("number is divisible by 4");
    } else if number % 3 == 0 {
        println!("number is divisible by 3");
    } else if number % 2 == 0 {
        println!("number is divisible by 2");
    } else {
        println!("number is not divisible by 4, 3, or 2");
    }

    // 条件必须是 bool 值
    // let number = 3;
    // if number {
    //     println!("number was three");
    // }

    let condition = true;
    let number = if condition { 5 } else { 6 };

    println!("The value of number is: {}", number);
}

#[allow(dead_code)]
fn if_let_else() {
    //
    let some_u8_value = Some(3u8);
    println!("{:?}", some_u8_value);
    // 匹配 Some(T)
    match some_u8_value {
        Some(3) => println!("three"),
        _ => (), // 匹配其他，什么都不做
                 // other => (), // 匹配其他，什么都不做
    }

    if let Some(3) = some_u8_value {
        println!("three");
    }

    // if let Some(50) = x {
    //     println!("Got 50");
    // } else if let Some(n) = y {
    //     println!("Matched, n = {}", n);
    // } else {
    //     println!("Nothing matched.");
    // }
}
